package com.seiko.danmaku.di

import android.util.Log
import com.seiko.danmaku.data.api.DanDanApi
import com.seiko.danmaku.data.api.DownloadApi
import com.seiko.danmaku.data.api.GzipInterceptor
import com.seiko.danmaku.util.DANDAN_API_BASE_URL
import com.seiko.danmaku.util.Gua
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import okio.GzipSource
import okio.buffer
import org.videolan.BuildConfig
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory

import retrofit2.create
import java.io.IOException
import java.util.concurrent.TimeUnit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    @DanDanClientQualifier
    fun provideDanDanClient(): OkHttpClient {
        val builder = OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .addInterceptor(GzipInterceptor())
        if (BuildConfig.DEBUG) {
            builder.addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
        }
        return builder.build()
    }

    @Provides
    @Singleton
    @DanDanRetrofitQualifier
    fun provideDanDanRetrofit(): Retrofit {
        return Retrofit.Builder()
            .client(client)
            .baseUrl(DANDAN_API_BASE_URL)
            .addConverterFactory(ScalarsConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideDanDanApiService(@DanDanRetrofitQualifier retrofit: Retrofit): DanDanApi {
        return retrofit.create()
    }


    @Provides
    @Singleton
    @DownloadClientQualifier
    fun provideDownloadClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .build()
    }

    @Provides
    @Singleton
    @DownloadRetrofitQualifier
    fun provideDownloadRetrofit(moshi: Moshi, @DownloadClientQualifier client: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .callFactory(client)
            .baseUrl("http://www.example.com")
            .build()
    }

    @Provides
    @Singleton
    fun provideDownloadApiService(@DownloadRetrofitQualifier retrofit: Retrofit): DownloadApi {
        return retrofit.create()
    }

    val client = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val originalRequest = chain.request()
            val request = originalRequest.newBuilder()
                .header("Accept-Encoding", "gzip")
                .build()
            val response = chain.proceed(request)
            Log.w("DANMAKU", response.code.toString())
            if (404 == response.code) {
                throw IOException("404")
            }
            val gzipResponseBody = response.body?: return@addInterceptor response
            val g = Gua()
            var r = GzipSource(gzipResponseBody.source()).buffer().readUtf8()
            if (g.verify(r)) {
                r = g.decode(r)
            }
            if (r.startsWith("\uFEFF")) {
                r = r.substring(1)
            }

            Log.w("DANMAKU", r)

            response.newBuilder()
                .body(r.toResponseBody(gzipResponseBody.contentType()))
                .build()
        }
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .build()
}